﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Reflection;

namespace KBEngine.Setting
{
    /// <summary>
    /// 由于KBEngine中的网络协议ID都由系统自动生成，如果不是用配套的SDK将很难与服务端对接协议。
	///	因此kbe提供了一种机制允许用户自定义网络协议的ID。
	///	这在某些情况下是比较好用的(例如: 传统协议对接方式都会有一个协议表，客户端匹配协议表中的协议然后解析)
    ///
    ///
    ///    详细说明请参考：http://kbengine.org/cn/docs/configuration/messages_fixed.html
    ///    
    /// PS:由于该文件的格式特殊性,请读取全部文本将"::"替换为"-"再序列化
    /// </summary>
    [Serializable]
    [XmlRoot("root")]
    public class MessagesFixedDefaults : IXmlSerializable
    {
        public List<Info> methodInfos = new List<Info>();

        public class Info
        {
            /// <summary>
            /// 方法id
            /// </summary>
            public ushort id = 0;

            /// <summary>
            /// 方法名称
            /// </summary>
            public string name = string.Empty;

            /// <summary>
            /// 方法描述
            /// </summary>
            public string desc = string.Empty;

            /// <summary>
            /// 方法参数
            /// </summary>
            public List<string> args = new List<string>();
        }

        #region XmlSerializable
        public XmlSchema GetSchema() => null;
        public void ReadXml(XmlReader reader)
        {
            methodInfos.Clear();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(reader);
            var root = xmlDoc.SelectSingleNode("root");
            foreach (XmlNode xmlNode in root.ChildNodes)
            {
                Info info = new Info();
                info.name = xmlNode.Name;
                if (xmlNode.SelectSingleNode("id").TryGetValue(out var txt))
                    info.id = ushort.Parse(txt);

                if (xmlNode.SelectSingleNode("descr").TryGetValue(out txt))
                    info.desc = txt;

                var tempNodeList = xmlNode.SelectNodes("arg");
                if (tempNodeList != null)
                {
                    foreach (XmlNode subNode in tempNodeList)
                    {
                        subNode.TryGetValue(out var type);
                        info.args.Add(type);
                    }
                }

                methodInfos.Add(info);
            }
        }
        public void WriteXml(XmlWriter writer)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlElement root = xmlDoc.CreateElement("root");
            xmlDoc.AppendChild(root);
            foreach (var item in methodInfos)
            {
                var node = xmlDoc.CreateElement(item.name);
                var idNode = xmlDoc.CreateElement("id");
                var descrNode = xmlDoc.CreateElement("descr");
                idNode.InnerText = item.id.ToString();
                descrNode.InnerText = item.desc;

                node.AppendChild(idNode);
                node.AppendChild(descrNode);
                root.AppendChild(node);

                foreach (var arg in item.args)
                {
                    var tempNode = xmlDoc.CreateElement("arg");
                    tempNode.InnerText = arg;
                    node.AppendChild(tempNode);
                }
            }
            foreach (XmlNode item in root)
            {
                item.WriteTo(writer);
            }
        }
        #endregion
    }
}
